package org.budo.dubbo.serialize.hessian;

import org.budo.dubbo.serialize.hessian.serializer.HibernateProxySerializer;
import org.budo.dubbo.serialize.hessian.serializer.PersistentBagSerializer;
import org.budo.dubbo.serialize.hessian.serializer.PersistentCollectionSerializer;
import org.budo.dubbo.serialize.hessian.serializer.PersistentSetSerializer;
import org.budo.dubbo.serialize.hessian.serializer.PersistentSortedSetSerializer;
import org.budo.support.lang.util.ReflectUtil;
import org.hibernate.collection.internal.PersistentBag;
import org.hibernate.collection.internal.PersistentSet;
import org.hibernate.collection.internal.PersistentSortedSet;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.proxy.HibernateProxy;

import com.alibaba.com.caucho.hessian.io.HessianProtocolException;
import com.alibaba.com.caucho.hessian.io.Serializer;
import com.alibaba.com.caucho.hessian.io.SerializerFactory;

/**
 * @author li
 * @version 1 (2014年8月22日 下午1:35:46)
 * @since Java7
 * @see com.alibaba.dubbo.common.serialize.support.hessian.Hessian2SerializerFactory
 */
@SuppressWarnings({ "rawtypes" })
public class BudoHessianSerializerFactory extends SerializerFactory {
    private static final boolean HAS_HIBERNATE = ReflectUtil.hasClass("org.hibernate.proxy.HibernateProxy");

    public static final SerializerFactory SERIALIZER_FACTORY = new BudoHessianSerializerFactory();

    public ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    public Serializer getSerializer(Class type) throws HessianProtocolException {
        if (!HAS_HIBERNATE) {
            return super.getSerializer(type); // 无 hibernate 
        }

        if (PersistentSortedSet.class.isAssignableFrom(type)) {
            return PersistentSortedSetSerializer.INSTANCE;
        }
        if (PersistentSet.class.isAssignableFrom(type)) {
            return PersistentSetSerializer.INSTANCE;
        }
        if (PersistentBag.class.equals(type)) {
            return PersistentBagSerializer.INSTANCE;
        }
        if (PersistentCollection.class.isAssignableFrom(type)) { // PersistentCollection 包含 List Set Map
            return PersistentCollectionSerializer.INSTANCE;
        }
        if (HibernateProxy.class.isAssignableFrom(type)) {
            return HibernateProxySerializer.INSTANCE;
        }

        return super.getSerializer(type);
    }
}
